package com.qzxy.premiumhotelsystem.service.impl;

import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.qzxy.premiumhotelsystem.common.constant.RedisKeyConstant;
import com.qzxy.premiumhotelsystem.common.constant.VipOrderStatusConstant;
import com.qzxy.premiumhotelsystem.common.constant.VipStatusConstant;
import com.qzxy.premiumhotelsystem.domain.dto.PayVipOrderDTO;
import com.qzxy.premiumhotelsystem.domain.dto.VipOrderPageDTO;
import com.qzxy.premiumhotelsystem.domain.dto.VipPageDTO;
import com.qzxy.premiumhotelsystem.domain.entity.Guests;
import com.qzxy.premiumhotelsystem.domain.entity.Vip;
import com.qzxy.premiumhotelsystem.domain.entity.VipOrders;
import com.qzxy.premiumhotelsystem.domain.entity.VipTypes;
import com.qzxy.premiumhotelsystem.domain.vo.VipOrderVO;
import com.qzxy.premiumhotelsystem.domain.vo.VipVO;
import com.qzxy.premiumhotelsystem.mapper.VipMapper;
import com.qzxy.premiumhotelsystem.common.result.PageResult;
import com.qzxy.premiumhotelsystem.common.result.Result;
import com.qzxy.premiumhotelsystem.mapper.VipTypesMapper;
import com.qzxy.premiumhotelsystem.service.GuestsService;
import com.qzxy.premiumhotelsystem.service.VipOrdersService;
import com.qzxy.premiumhotelsystem.mapper.VipOrdersMapper;
import com.qzxy.premiumhotelsystem.utils.BaseContext;
import com.qzxy.premiumhotelsystem.utils.RedisUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import jakarta.annotation.Resource;
import java.util.Date;
import java.util.List;

/**
* @author 14912
* @description 针对表【vip_orders】的数据库操作Service实现
* @createDate 2024-09-13 22:48:27
*/
@Service
@Slf4j
public class VipOrdersServiceImpl extends ServiceImpl<VipOrdersMapper, VipOrders>
        implements VipOrdersService{

    @Resource
    private VipOrdersMapper vipOrdersMapper;

    @Resource
    private RedisUtil redisUtil;

    @Resource
    private GuestsService guestsService;

    @Resource
    private VipMapper vipMapper;

    @Resource
    private VipTypesMapper vipTypesMapper;


    @Override
    public Result createOrder(Integer vipTypeId) {
        log.info("开始购买会员，会员类型id：{}",vipTypeId);
        //TODO 暂时假设从这取，到时候等用户模块完善后看是从这还是redis
        String telephone = (String) StpUtil.getLoginId();
        Guests guests = guestsService.getByTelephone(telephone);
        Integer guestId = guests.getGuestId();
        //要是用户存在未支付的订单，就不能在购买，不管是不是相同类型的
        LambdaQueryWrapper<VipOrders> lqw1 = new LambdaQueryWrapper<>();
        lqw1.eq(VipOrders::getGuestId,guestId);
        lqw1.eq(VipOrders::getStatus,VipOrderStatusConstant.VIP_ORDER_PENDING);
        List<VipOrders> vipOrdersList = vipOrdersMapper.selectList(lqw1);
        if (!CollUtil.isEmpty(vipOrdersList)){
            return Result.build(null,500,"当前存在未支付的vip订单，请先去支付");
        }

        //检查用户是否已经是该会员 |当过有效期，第二天会vip表的status会变为失效
        LambdaQueryWrapper<Vip> lqw = new LambdaQueryWrapper<>();
        lqw.eq(Vip::getGuestId,guestId);
        lqw.eq(Vip::getVipTypeId,vipTypeId);
        lqw.eq(Vip::getStatus,VipStatusConstant.VIP_VALID);
        if (vipMapper.selectOne(lqw) != null) {
            return Result.build(null,500,"该会员还在有效期，无法重复激活（当天失效的会员第二天凌晨0点后才可继续购买）");
        }

        VipOrders vipOrders = VipOrders.builder().vipOrderId(IdUtil.simpleUUID())
                .guestId(guestId)
                .vipTypeId(vipTypeId)
                .status(VipOrderStatusConstant.VIP_ORDER_PENDING)
                .purchaseTime(new Date())
                .build();
        vipOrdersMapper.insert(vipOrders);

        return Result.ok(vipOrders.getVipOrderId());

    }

    @Override
    @Transactional
    public Result payVipOrder(PayVipOrderDTO payVipOrderDTO) {
        log.info("开始支付会员，PayVipOrderDTO：{}",payVipOrderDTO);

        if(!StrUtil.equals("余额支付",payVipOrderDTO.getPayMethod())){
            // 目前只支持余额支付
            return Result.build(null,500,"抱歉，目前只支持余额支付");
        }

        VipOrders vipOrders = vipOrdersMapper.selectVipOrder(payVipOrderDTO.getVipOrderId());
        if (vipOrders == null || !VipOrderStatusConstant.VIP_ORDER_PENDING.equals(vipOrders.getStatus())){
            return Result.build(null,500,"订单不存在或已支付");
        }
        //从redis获取相关会员等级信息
        VipTypes vipTypes = redisUtil.getCacheObject(RedisKeyConstant.VIP_TYPE_KEY + vipOrders.getVipTypeId());
        log.info("获取会员相关信息，VipTypes：{}",vipTypes);

        //以防管理员没装配
        if (vipTypes == null) {
            vipTypes = vipTypesMapper.selectById(vipOrders.getVipTypeId());
        }
        //扣减余额
        guestsService.deductMoney(payVipOrderDTO.getPayPwd(),vipTypes.getPrice());

        Date time = new Date(); // 定义当前时间

        //修改订单状态为已支付
        vipOrders.setStatus(VipOrderStatusConstant.VIP_ORDER_PAID);
        vipOrders.setPayTime(time);
        //已设置版本号进行乐观锁判断
        int updated = vipOrdersMapper.updateById(vipOrders);
        if (updated == 0) {
            return Result.build(null,500,"订单支付失败，请重试");
        }

        log.info("准备激活会员");
        //激活会员 |往vip表插入相关信息
        //TODO 暂时假设从这取，到时候等用户模块完善后看是从这还是redis
        String telephone = (String) StpUtil.getLoginId();
        Guests guests = guestsService.getByTelephone(telephone);
        Integer guestId = guests.getGuestId();

        //检查用户是否已经是该会员 |当过有效期，第二天会vip表的status会变为失效
        LambdaQueryWrapper<Vip> lqw = new LambdaQueryWrapper<>();
        lqw.eq(Vip::getGuestId,guestId);
        lqw.eq(Vip::getVipTypeId,vipTypes.getVipTypeId());
        lqw.eq(Vip::getStatus,VipStatusConstant.VIP_VALID);
        if (vipMapper.selectOne(lqw) != null) {
            return Result.build(null,500,"该会员还在有效期，无法重复激活（当天失效的会员第二天凌晨四点后才可继续购买）");
        }

        Date endTime = DateUtil.offsetMonth(time, 1); // 将 time 增加一个月,默认会员时长都是1个月
        Vip vip = Vip.builder().guestId(guestId)
                .vipTypeId(vipTypes.getVipTypeId())
                .startTime(time)
                .endTime(endTime)
                .status(VipStatusConstant.VIP_VALID)
                .build();

        vipMapper.insert(vip);

        //用户购买了，删掉缓存，下次读取重新加载
        String cacheKey = RedisKeyConstant.VIP_KEY + guestId;
        redisUtil.deleteObject(cacheKey);

        //修改订单状态为已完成
        vipOrders.setStatus(VipOrderStatusConstant.ORDER_COMPLETED);
        vipOrdersMapper.updateById(vipOrders);

        return Result.ok("支付成功并激活" + vipTypes.getVipType() + "会员，有效时长为1个月");
    }


    @Override
    public List<VipOrderVO> getOrders() {
        //TODO 暂时假设从这取，到时候等用户模块完善后看是从这还是redis
        String telephone = (String) StpUtil.getLoginId();
        Guests guests = guestsService.getByTelephone(telephone);
        Integer guestId = guests.getGuestId();

        log.info("查询用户：{}已经激活的VIP会员信息",guestId);
        List<VipOrderVO> orderVOS = vipOrdersMapper.getOrdersByGuestId(guestId);
        return orderVOS;
    }

    @Override
    public Result<PageResult> pageVipOrderVos(VipOrderPageDTO vipOrderPageDTO) {
        IPage<VipOrderVO> page = new Page<>(vipOrderPageDTO.getPageNo(),vipOrderPageDTO.getPageSize());
        vipOrdersMapper.pageQueryVOrdersWithVipType(page,vipOrderPageDTO);

        return Result.ok(new PageResult(page.getTotal(),page.getRecords()));
    }

    @Override
    public Result<PageResult> pageVipVos(VipPageDTO vipPageDTO) {
        IPage<VipVO> page = new Page<>(vipPageDTO.getPageNo(),vipPageDTO.getPageSize());
        vipMapper.pageQueryVipWithVipType(page,vipPageDTO);

        return Result.ok(new PageResult(page.getTotal(),page.getRecords()));
    }
}




